package futbol.tacticas.concursantes.qualitycode.ctrlteam;

import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Vector;

import futbol.Bola;
import futbol.iu.PintarCampo;
import futbol.tacticas.Comando;
import futbol.tacticas.SituacionJugadores;
import futbol.tacticas.concursantes.qualitycode.QCodeTactica;
import futbol.tacticas.concursantes.qualitycode.common.Campo;
import futbol.tacticas.concursantes.qualitycode.common.QBall;
import futbol.tacticas.concursantes.qualitycode.common.QPlayer;
import futbol.tacticas.concursantes.qualitycode.common.QTeam;
import futbol.tacticas.concursantes.qualitycode.common.QUtils;
import futbol.tacticas.concursantes.qualitycode.ctrlteam.QCtrlPlayer.Funcion;
import futbol.tacticas.concursantes.qualitycode.ctrlteam.QPases.AutoPase;
import futbol.tacticas.concursantes.qualitycode.opponent.QOpponentTeam;

public class QCtrlTeam extends QTeam<QCtrlPlayer>
{
  // private enum Status {FIRST_KICKOFF, ATTACKING, DEFENDING,};
  // private Status status = Status.FIRST_KICKOFF;

  private SituacionJugadores sj;
  private QBall ball = null;
  private QOpponentTeam opponentTeam = null;
  private QCtrlPlayer controlador = null;

  private Campo campoDelanteros = null;
  private Campo campoMedio = null;
  private Campo campoAtras = null;
  private Campo campoAutoPase = null;
  private int firstKick = 0;

  public QCtrlTeam(String ID)
  {
    super(ID);

    addPlayer(1, -130, 0, QCodeTactica.FORCE_7_MAX, QCtrlPlayer.Funcion.PORTERO);

    addPlayer(2, -20, -60, QCodeTactica.FORCE_4_MIN, QCtrlPlayer.Funcion.DEFENSA);
    addPlayer(3, -20, 60, QCodeTactica.FORCE_5, QCtrlPlayer.Funcion.DEFENSA);

    addPlayer(4, 30, -60, QCodeTactica.FORCE_4_MIN, QCtrlPlayer.Funcion.DEFENSA);
    addPlayer(5, 30, 60, QCodeTactica.FORCE_5, QCtrlPlayer.Funcion.DEFENSA);

    addPlayer(6, -30, 0, QCodeTactica.FORCE_5, QCtrlPlayer.Funcion.DEFENSA);
    addPlayer(7, 30, 0, QCodeTactica.FORCE_6, QCtrlPlayer.Funcion.DEFENSA);
    
    addPlayer(8, 120, -100, QCodeTactica.FORCE_7_MAX, QCtrlPlayer.Funcion.DELANTERO);
    addPlayer(9, 50, 35, QCodeTactica.FORCE_5, QCtrlPlayer.Funcion.RECUPERA_DEFENSA);
    addPlayer(10, 90, -80, QCodeTactica.FORCE_7_MAX, QCtrlPlayer.Funcion.DELANTERO);
    
    
    addPlayer(11, 180, -35, QCodeTactica.FORCE_6, QCtrlPlayer.Funcion.RECUPERA_DEFENSA);
  }

  private void addPlayer(int ID, int x, int y, int force, QCtrlPlayer.Funcion funcion)
  {
    final QCtrlPlayer player = new QCtrlPlayer(this, ID - 1, funcion);
    player.setup(new Point(x, y), force);
    players.add(player);
  }

  @Override
  public void reset()
  {
    super.reset();
    controlador = null;
    firstKick = 0;
  }

  private List<QCtrlPlayer> playersXFuncion(Funcion funcion)
  {
    final List<QCtrlPlayer> playersFuncion = new ArrayList<QCtrlPlayer>();
    for (QCtrlPlayer player : players)
    {
      if (player.isFuncion(funcion))
        playersFuncion.add(player);
    }
    return playersFuncion;
  }

  public boolean ganando()
  {
    return getGoals() > opponentTeam.getGoals();
  }

  public boolean perdiendo()
  {
    return getGoals() < opponentTeam.getGoals();
  }

  public boolean empate()
  {
    return getGoals() == opponentTeam.getGoals();
  }

  QCtrlPlayer portero()
  {
    return players.get(0);
  }
  // -------------------------------------------------------------------------------
  private QCtrlPlayer encontrarControlador()
  {
    if (controlador != null)
    {
      final int turnos = controlador.turnosInterseptarBola(ball.getFutureBalls());
      final int opponentTurnos = opponentTeam.turnosInterseptor(ball.getFutureBalls());
      if (turnos < opponentTurnos)
      {
        final int porteroTurnos = portero().turnosInterseptarBola(ball.getFutureBalls());
        if (porteroTurnos-2 <= turnos && porteroTurnos < opponentTurnos)
          return portero();
        
        return controlador;
      }
    }

    QCtrlPlayer best = getPlayer(0);
    int turnos = best.turnosInterseptarBola(ball.getFutureBalls());
    for (int i = 1; i < players.size(); i++)
    {
      final int nTurnos = players.get(i).turnosInterseptarBola(ball.getFutureBalls());

      if (players.get(i).isPasoAotro() && nTurnos == 0)
        continue;

      if (nTurnos < turnos)
      {
        turnos = nTurnos;
        best = players.get(i);
      }
    }
    return best;
  }

  public Vector<Comando> getComandos(SituacionJugadores sj, QOpponentTeam opponentTeam, QBall currentBall)
  {
    ball = currentBall;
    setControler(encontrarControlador());
    this.opponentTeam = opponentTeam;
    
    if (controlador.puedeAnotar(ball))
    {
      controlador.cmdTirarAMarco(currentBall);
    }
    else
    {
      if (campoDelanteros == null)
      {
        campoDelanteros = new Campo(40, 110, 100, 0, -100, 10, 10, 10);
        campoDelanteros.setDistanciaBola(280);
        
        campoMedio = new Campo(60, 0, 120, -30, -130, 10, 10, 10);
        
        
        campoAtras = new Campo(60,40, 120, -100, -120, 10, 10, 10);
        campoAutoPase = new Campo(15, 160, 120, -160, -120, 2, 5, 5);
        //PintarCampo.qcode = this;
      }
      
      /*if (ball.getX() < 0)
        campoDelanteros.equals(170);
      else
        campoDelanteros.equals(100);/**/
      
      campoDelanteros.update(ball, opponentTeam.getPlayers());
      campoMedio.update(currentBall, opponentTeam.getPlayers());      
      //campoAutoPase.update(currentBall, opponentTeam.getPlayers());
      
      /*if (firstKick>0)
      {
        firstKick--;
        controlador.cmdGolpearBola(currentBall, portero().getPos());
      }
      else*/
        controlador.exec();

      organizarDefensa();
      moveDelantero();
      moveMedio();

      if (controlador.canGolpear(currentBall) && controlador.getForce() == QCodeTactica.FORCE_7_MAX)
      {
        ball.golpearBola(controlador, 1000, ball.getY());
        ball.getFutureBalls();
      }
    }
    
    if (portero().getComandos().size() == 0)
    {
      if (ball.getY() < 30 && ball.getY() > -30)      
        portero().cmdIrA(new Point(-140, ball.getY()));
      else
        portero().cmdIrA(new Point(-140, 0));
    }
    
    if (!ball.canGolpear(controlador))
    {
      final List<? extends QPlayer> opponents = opponentTeam.cercania(ball.getPos());
      final QPlayer opponent = opponents.get(0);
      if (ball.canGolpearIgnorarSpeed(opponent))
      {
        final List<QCtrlPlayer> players = cercania(ball.getPos());
        if (ball.canGolpearIgnorarSpeed(players.get(0)))
        {
          players.get(0).cmdGolpearBola(currentBall, new Point(-opponent.getX()*5, -opponent.getY()*5));
        }
      }
    }
    
    QCtrlPlayer p10 = players.get(8);
    if (controlador != p10)
    { 
      if (p10.getY() < -140) //parche ya no hay tiempo
      {
        p10.cmdIrA(new Point(p10.getX(), 0));
      }
      else if (p10.getX() > 150) //parche ya no hay tiempo
      {
        p10.getComandos().clear();
      }
    }
    // ----------------------------------------------------- Paso final
    final Vector<Comando> comandos = new Vector<Comando>();
    for (QCtrlPlayer player : players)
    {
      comandos.addAll(player.getComandos());
      player.clearComandos();
    }

    return comandos;
  }

  private void organizarDefensa()
  {
    final List<QPlayer> atacando = opponentTeam.atacando();

    List<QCtrlPlayer> defensas = playersXFuncion(Funcion.DEFENSA);
    defensas.remove(controlador);

    Collections.sort(atacando, new Comparator<QPlayer>()
    {
      public int compare(QPlayer o1, QPlayer o2)
      {
        return o1.getX() - o2.getX();
      }
    });

    for (int i = 0; defensas.size() > 0 && i < atacando.size(); i++)
    {
      defensas = cercania(atacando.get(i), defensas);
      final Point p = atacando.get(i).getPos();
      final int offset = (QBall.KICK_RADIO / 2)+1;

      if (ball.getX() < p.x)
        p.translate(-offset, 0);
      else
        p.translate(offset, 0);

      if (ball.getY() < p.y)
        p.translate(0, -offset);
      else
        p.translate(0, offset);

      defensas.remove(0).cmdIrA(p);
    }
  }

  // --------------------------------------------------------

  public void adelantarSoporte()
  {
  }

  public QBall getBall()
  {
    return ball;
  }

  public QOpponentTeam getOpponentTeam()
  {
    return opponentTeam;
  }

  public List<QCtrlPlayer> cercania(QPlayer player, List<QCtrlPlayer> players)
  {
    final List<QCtrlPlayer> cercania = QUtils.cercania(players, player.getPos());
    cercania.remove(player);
    return cercania;
  }

  public QCtrlPlayer jugadorCercano(QPlayer player, List<QCtrlPlayer> excluirPlayers, boolean soloAdelante)
  {
    final int nExc[] = new int[excluirPlayers.size() + 1];
    for (int i = 0; i < excluirPlayers.size(); i++)
      nExc[i] = excluirPlayers.get(i).getID();

    nExc[nExc.length - 1] = player.getID();

    int dev1[] = sj.getInfoMasCercano(sj.getMisJugadores(), sj.getMisJugadores()[player.getID()], nExc, soloAdelante);
    if (dev1[0] == -1)
      return null;

    return players.get(dev1[0]);
  }

  public QCtrlPlayer jugadorCercano(QPlayer player, boolean soloAdelante)
  {
    int nExc[] = { player.getID() };
    int dev1[] = sj.getInfoMasCercano(sj.getMisJugadores(), sj.getMisJugadores()[player.getID()], nExc, soloAdelante);
    if (dev1[0] == -1)
      return null;

    return players.get(dev1[0]);
  }

  public void setControler(QCtrlPlayer controlador)
  {
    if (this.controlador == null)
    {
      this.controlador = controlador;
      this.controlador.setFuncion(QCtrlPlayer.Funcion.CONTROLADOR);
      setupSoporte();
    }
    else if (this.controlador != controlador)
    {
      this.controlador.nuevoControlador();
      this.controlador.resetFuncion();
      this.controlador = controlador;
      this.controlador.setFuncion(QCtrlPlayer.Funcion.CONTROLADOR);
      controlador.exec();      
    }
  }

  private void setupSoporte()
  {
    /***************************************************************************
     * List<QCtrlPlayer> players = cercania(controlador); for (QCtrlPlayer
     * ctrlPlayer : players) if (ctrlPlayer.isFuncion(Funcion.SOPORTE))
     * ctrlPlayer.resetFuncion();
     * 
     * //players.removeAll(playersXFuncion(Funcion.DEFENSA)); //players =
     * QUtils.filtrar(players, controlador.getPos(), QPases.MIN_DIST, false);
     * 
     * for (int i = 0; i < 3; i++) players.get(i).setFuncion(Funcion.SOPORTE);/
     **************************************************************************/
  }

  /*
   * private void moveSoporte() { for (QCtrlPlayer ctrlPlayer : players) if
   * (ctrlPlayer.isFuncion(Funcion.SOPORTE) && ctrlPlayer.getComandos().size() ==
   * 0) ctrlPlayer.moveSoporte(controlador); }
   */

  public boolean isControlador(QCtrlPlayer ctrlPlayer)
  {
    return controlador == ctrlPlayer;
  }

  @Override
  public void pintar(boolean over, Graphics gdb)
  {
    super.pintar(over, gdb);
    campoMedio.pintar(over, gdb);
    campoDelanteros.pintar(over, gdb);
    
    ball.pinar(over, gdb);
  }

  public void moveDelantero()
  {
    final List<QCtrlPlayer> delanteros = playersXFuncion(Funcion.DELANTERO);
    updateCampo(delanteros, campoDelanteros);
  }

  public void moveMedio()
  {
    final List<QCtrlPlayer> recuperadores = playersXFuncion(Funcion.RECUPERA_DEFENSA);
    updateCampo(recuperadores, campoMedio);
  }

  public void updateCampo(List<QCtrlPlayer> players, Campo campo)
  {
    for (QCtrlPlayer player : players)
    {
      if (player.getComandos().size() == 0)
      {
        final Point p = campo.mejorCelda(player.getPos(),0);
        if (p != null)
        {
          player.cmdIrA(p);
          final QPlayer futurePlayer = new QPlayer(player);
          futurePlayer.updatePos(p);
          campo.invalidate(futurePlayer);
        }
      }
    }
  }
  
  public Campo getCampoAutoPase()
  {
    return campoAutoPase;
  }
}
